#ifndef EP3D_DOUBLEBUFFER_H
#define EP3D_DOUBLEBUFFER_H
#include "EP3DBase.h"
#include "EP3DArray.h"
#include "EP3DCriticalSection.h"
namespace EP3D
{
	template<class T>
	class DoubleBuffer
	{
	public:
		DoubleBuffer()
			;m_uiRead(0)
			,m_uiWrite(1)
			,m_uiCapacity(0)
		{
		}

		DoubleBuffer(uint uiCapacity)
			;m_uiRead(0)
			,m_uiWrite(1)
			,m_uiCapacity(uiCapacity)
		{
			m_akBuffer[0].Reserve(m_uiCapacity);
			m_akBuffer[1].Reserve(m_uiCapacity);
		}

		~DoubleBuffer()
		{
		}

		void Add(const T& elem)
		{
			m_kLocks[m_uiWrite].Lock();
			m_akBuffer[m_uiWrite].Push(elem);
			m_kLocks[m_uiWrite].Unlock();
		}

		T Pop()
		{
			m_kLocks[m_uiRead].Lock();
			T t = m_akBuffer[m_uiRead].Front();
			m_akBuffer[m_uiRead].Pop();
			m_kLocks[m_uiRead].Unlock();

			return t;
		}

		void SwapBuffer()
		{
			uint uiTemp = m_uiRead;
			m_uiRead = m_uiWrite;
			m_uiWrite = uiTemp;
		}

	private:
		Array<T> m_akBuffer[2];
		uint m_uiRead;
		uint m_uiWrite;
		uint m_uiCapacity;
		CriticalSection m_kLocks[2];
	}
}
#endif